import { message } from 'ant-design-vue'
import axios from 'axios'
import { storage } from '@/utils/storage'
import router from '@/router'
// import qs from 'qs'
import type { Canceler, AxiosInstance, AxiosRequestConfig } from 'axios'
import type { ApiRequest, HttpResponse } from '@/types/apis.d'
const CancelToken = axios.CancelToken
const ERROR_CODE: any = {
  400: '请求错误(400)',
  401: '未授权,请登录(401)',
  403: '拒绝访问(403)',
  404: `请求地址出错(404)`,
  405: '请求方法未允许(405)',
  408: '请求超时(408)',
  500: '服务器内部错误(500)',
  501: '服务未实现(501)',
  502: '网络错误(502)',
  503: '服务不可用(503)',
  504: '网络超时(504)',
  505: 'HTTP版本不受支持(505)'
}
class HttpRequest {
  private baseUrl: string
  private pending: Record<string, Canceler>

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl
    this.pending = {}
  }
  /** 获取配置 */
  private getConfig() {
    return {
      baseURL: this.baseUrl,
      headers: {
        'Content-Type': 'application/json;charset=utf-8'
      },
      timeout: 15000
    }
  }
  private removePending(key: string, isRequest = false) {
    if (this.pending[key] && isRequest) {
      this.pending[key]('取消重复请求')
    }
    delete this.pending[key]
  }

  private interceptors<D>(instance: AxiosInstance) {
    // 请求拦截
    instance.interceptors.request.use((config) => {
      console.log('config: ', config)
      const token = storage.get('previewToken') || storage.get('token')
      if (token) {
        config!.headers!.Authorization = 'Bearer ' + token
      } else {
        router.push('/sign-in')
      }
      const key = config.url + '&' + config.method
      // this.removePending(key, true)

      config.cancelToken = new CancelToken((cancel) => (this.pending[key] = cancel))
      return config
    })
    // 响应拦截

    instance.interceptors.response.use(
      (res) => {
        const key = res.config.url + '&' + res.config.method
        // this.removePending(key)
        if (res.status === 200) {
          const resp: HttpResponse<D> = {
            code: 0,
            data: res.data
          }
          return Promise.resolve<HttpResponse<D>>(resp)
        }
        message.error(res.statusText, 5)
        return Promise.reject(res)
      },
      (err) => {
        // errHandle(err)
        // if (err.message) return message.error(err.message)
        console.log('err: ', err)
        const code = err.response.data.code
        console.log('code: ', code)
        if (code) {
          if (code === 401) {
            router.replace({ name: 'SignIn' })
            storage.remove('token')
            storage.remove('user')
          }
          message.destroy()
          message.error(err.response.data.message || err.message, 5)
        } else {
          message.error(ERROR_CODE[err.response.status], 5)
        }
        return Promise.reject(err)
      }
    )
  }

  http<D = any>(options: AxiosRequestConfig) {
    const config = Object.assign(this.getConfig(), options)
    const instance = axios.create(config)
    this.interceptors(instance)
    return instance.request<HttpResponse<D>>(config)
  }

  get<T extends keyof ApiRequest, D>(
    url: string,
    params?: ApiRequest[T],
    config?: AxiosRequestConfig
  ): Promise<HttpResponse<D>> {
    const options = Object.assign({ url, params }, config)
    return new Promise((resolve, reject) => {
      this.http(options)
        .then((res) => {
          return resolve(res.data as unknown as HttpResponse<D>)
        })
        .catch((err) => {
          return reject(err)
        })
    })
  }

  post<T extends keyof ApiRequest, D>(
    url: string,
    data?: ApiRequest[T],
    config?: AxiosRequestConfig
  ): Promise<HttpResponse<D>> {
    const options = Object.assign({ url, data, method: 'POST' }, config)
    return new Promise((resolve, reject) => {
      this.http(options)
        .then((res) => {
          return resolve(res as unknown as HttpResponse<D>)
        })
        .catch((err) => {
          return reject(err)
        })
    })
  }
  // download<T extends keyof ApiRequest>(
  //   url: string,
  //   params?: ApiRequest[T],
  //   config?: AxiosRequestConfig
  // ): Promise<{
  //   fileName: string
  //   content: Blob
  // }> {
  //   const options = Object.assign({ url, params }, config)
  //   return new Promise((resolve, reject) => {
  //     const token = storage.get('token')
  //     this.baseUrl = import.meta.env.VITE_BASE_URL
  //     const config = Object.assign(this.getConfig(), options, {
  //       method: 'get',
  //       paramsSerializer: (v: ApiRequest[T]) =>
  //         qs.stringify(v, {
  //           arrayFormat: 'repeat'
  //         })
  //     })
  //     if (token) {
  //       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  //       config!.headers!.Authorization = 'Bearer ' + token
  //     }

  //     const instance = axios.create({ ...config, responseType: 'blob' })
  //     return instance
  //       .request(config)
  //       .then((res) => {
  //         console.log('res: ', res)
  //         // const contentDisposition = res.headers['content-disposition']
  //         // const temp = contentDisposition.split('filename=')
  //         // console.log('temp: ', temp)
  //         // const fileName = temp?.length ? temp[1].replace('"', '') : ''
  //         const fileName = '模板'
  //         resolve({ fileName, content: res.data })
  //       })
  //       .catch((err) => reject(err))
  //   })
  // }
}
export default HttpRequest
